﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using HA.ModFlow.Infrastructure;


namespace HA.ModFlow.Domain.DomainLayer
{
    /// <summary>
    /// 读取ModFlow输出的水头文件
    /// </summary>
    public class HeadFileDataSetReader : DataSetReader
    {
        #region 构造函数

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path">文件路径（不包括文件名和后缀）</param>
        /// <param name="i">主网格 RowsNumber</param>
        /// <param name="j">主网格 ColsNumber</param>
        /// <param name="k"> 主网格 LayerNumber</param>
        /// <param name="nPeriods">应力期总个数</param>
        /// <param name="stressPeriodNSTP">各应力期的时间步数</param>
        /// <param name="oc">应力期输出类型</param>
        public HeadFileDataSetReader(string path, int i, int j, int k, int nPeriods, List<int> stressPeriodNSTP, OutputControl oc,List<int[,]> iBounds)
        {

            this._path = path;
            this._i = i;
            this._j = j;
            this._k = k;
            this._nPeriods = nPeriods;
            this._stressPeriodNSTP = stressPeriodNSTP;
            this._oc = oc;


            this.iBoundValue = iBounds;

        }


        #endregion


        #region 字段属性  主要是相关数据的配置参数信息

        //List<CellCenterDataSet3d> _headCellCenterDataSet3d;
        ///// <summary>
        ///// 
        ///// </summary>
        //public List<CellCenterDataSet3d> HeadCellCenterDataSet3d
        //{
        //    get { return _headCellCenterDataSet3d; }
        //    set { _headCellCenterDataSet3d = value; }
        //}

        /// <summary>
        /// 文件路径
        /// </summary>
        private string _path;
        /// <summary>
        /// RowNumber
        /// </summary>
        private int _i;
        /// <summary>
        /// ColNumber
        /// </summary>
        private int _j;
       /// <summary>
       /// LayerNumber
       /// </summary>
        private int _k;
        /// <summary>
        /// 应力期个数
        /// </summary>
        private int _nPeriods;
        /// <summary>
        /// 各应力期的时间步数
        /// </summary>
        private List<int> _stressPeriodNSTP;

        private OutputControl _oc;


        private List<int[,]> iBoundValue;


        #endregion


        #region 内部方法

        #endregion


        #region 公用方法

        /// <summary>
        /// 该方法是从 MFFileReader 中拷贝过来的，具体作用（被窗体winImportTxtCsvFile中的确定按钮的单击事件调用）不太明确，暂时放这里
        /// </summary>
        /// <param name="Count"></param>
        /// <param name="FileName"></param>
        /// <returns></returns>
        public List<double[]> GetReslutData(int Count, string FileName)
        {
            List<double[]> ArryResultData = new List<double[]>();
            if (System.IO.File.Exists(FileName))
            {
                //try
                //{
                using (StreamReader mReader = new StreamReader(FileName))
                {

                    int mLen = 11;//截取的字符数                       
                    while (mReader.Peek() >= 0)
                    {
                        string mStr = mReader.ReadLine();

                        //==============================
                        //int P = HAUtil.FileImporter.GetStringNumber(mStr, " ");
                        double[] arry = new double[Count];


                        int X = 10;
                        int Y = 1;
                        int C = 0;
                        if (mStr.Trim() != "")
                        {
                            for (int i = 0; i < Count; i++)
                            {
                                if ((i) < X * Y)
                                {
                                    string str = mStr.Substring(C * mLen, mLen);
                                    arry[i] = Convert.ToDouble(str);
                                    C++;
                                }
                                else
                                {
                                    Y++;
                                    mStr = mReader.ReadLine();
                                    C = 0;
                                    string str = mStr.Substring(C * mLen, mLen);
                                    C++;
                                    arry[i] = Convert.ToDouble(str);
                                }
                            }
                        }
                        ArryResultData.Add(arry);
                    }
                }
                //}
                //catch
                //{
                //    return null;
                //}
            }
            else
            {
                return null;
            }

            return ArryResultData;

        }

        #endregion

        #region 实现父类的抽象方法


        /// <summary>
        /// 返回指定的 index 的网格数据 例如：第三天
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public override DataSet ReadData(int index)
        {
            //index的具体含义还不太明确，如何根据 index 定位到文件中数据的位置。。。。。。。。。。。。

            //该方法的实现有两种方案：1，直接根据 index 定位文件数据位置，读取；
            //2，首先调用 另一个读取文件数据的方法然后根据 index 确定读取的数据在 List 中的索引位置




            return null;


            //throw new NotImplementedException();



        }

        /// <summary>
        /// 对外接口函数 返回一个网格数据的集合  文件大小 0 kb 或者读取过程出错返回  List<DataSet> 的 Count=0
        /// </summary>
        public override List<DataSet> ReadData()
        {

            //说明：该读取文件数据的方法的做了一些前提的假设  1，文件内容很规范，从第一行开始就是数据信息，且数据完整
            //2，数据之间没有空行

            //其他的情况可能会导致该方法读取文件错误



            #region 一些数据的有效性的检验

             //缺少对于配置信息的一些有效性检验

            #endregion


            //以 15*15*3 的网格 ；总共 4 个应力期 ；每个应力期 时间步数都为 10   ；输出所有时间步数应力期；输出格式 _10G11_4。

            #region 定义一些控制信息

            int mLen = 12;//每个完整的数据占12位  包括负号的情况
            int maxLength = 10;//默认每行最多有10个完整数据


            //总共需要的网格数

            int gridNumber = 0;

            //如果是应力期每个步长输出
            //gridNumber=第一个应力期时间步数 + 第二个应力期时间步数 + 第三个应力期时间步数 + 第四个应力期时间步数 
            //如果是应力期输出最后一个步长
            //gridNumber=应力期总的个数

            if (this._oc.IsAllStepOutput == true)
            {
                for (int nstp = 0; nstp < this._stressPeriodNSTP.Count; nstp++)
                {
                    gridNumber = gridNumber + _stressPeriodNSTP[nstp];
                }
                //共有 40 个网格
            }
            else
            {
                gridNumber = _nPeriods;
                //共有4个网格

            }




            //网格每个I（Row）在文件中占多少行
            //默认设置 _10G11_4   每行最多10个完整数据，每个数据占11位，显示4位小数，例如：-0.2166E-02
            if (_j <= 10)
            {
                //1行  
            }
            if (10 < _j && _j <= 20)
            {
                //2行 
            }
            //类推  有待验证
            double result = _j * 0.1;//默认每行最多 10 个完整数据 所以乘以 0.1
            int lineNum = (int)Math.Ceiling(result);
            //占 2 行


            //网格每层在文件中站多少行
            int layerLineNumber = 0;
            //layerLineNumber= I（RowsNumber）* 网格每个I（Row）在文件中占行

            layerLineNumber = lineNum * this._i;
            //30 行


            //每个网格在文件站多少行

            int gridLineNumber = 0;
            //gridLineNumber=layerLineNumber*K;
            gridLineNumber = layerLineNumber * _k;
            //90 行



            //文件总的数据行数

            int fileLineNumber = 0;
            //fileLineNumber=gridLineNumber * gridNumber(应力期总个数)
            fileLineNumber = gridLineNumber * gridNumber;
            //3600 行



            #endregion

            //存储返回的数据
            List<DataSet> _headDataSet = new List<DataSet>();
            //计算过程的临时存储
            List<CellCenterDataSet3d> _headCellCenter = new List<CellCenterDataSet3d>();

            //List<Grid3dValue> _heads = new List<Grid3dValue>();


            //从文件读取数据

            string FileName = this._path + "IHEDUN.dat";

            if (System.IO.File.Exists(FileName))
            {
                #region

                StreamReader sr = new StreamReader(FileName);

                try
                {

                    _headCellCenter.Clear();
                    //_heads.Clear();


                    #region 记录 应力期_时间步长_传输步长

                    bool isAllStepOutputType = this._oc.IsAllStepOutput;//应力期的输出类型
                    int stressIndex = 1;//第几个应力期  应力期总个数 this._stressPeriodNSTP.Count
                    int timeIndex = 1;//第几个时间步长   某个应力期的总时间步长 _stressPeriodNSTP[i]=10
                    //int transIndex = 1;

                    #endregion


                    for (int gnum = 0; gnum < gridNumber; gnum++)//总共多少个网格的数据
                    {

                        #region 更新应力期 时间步长的标记

                        if (isAllStepOutputType == true)
                        {

                            if (gnum == 0)
                            {
                                stressIndex = 1;
                                timeIndex = 1;
                            }
                            else
                            {
                                timeIndex = timeIndex + 1;

                                if (timeIndex <= this._stressPeriodNSTP[stressIndex - 1])
                                {
                                    //timeIndex = timeIndex + 1;

                                }
                                else if (timeIndex > this._stressPeriodNSTP[stressIndex - 1])
                                {
                                    timeIndex = 1;
                                    stressIndex = stressIndex + 1;
                                }
                            
                            }
    

                        }
                        else
                        {

                            if (gnum == 0)
                            {
                                stressIndex = 1;
                                timeIndex = this._stressPeriodNSTP [stressIndex -1];
                            }
                            else
                            {
                                stressIndex = stressIndex + 1;

                                timeIndex = this._stressPeriodNSTP[stressIndex-1];
                              
                            }

                           
                        }

                        #endregion



                        double[, ,] gridValue = new double[_i, _j, _k];


                        //Grid3dValue Grid3d = new Grid3dValue(_i, _j, _k);


                        //从文件中读取对应网格的信息

                        int row = 0;
                        int col = 0;
                        int layer = 0;


                        #region 从文件读取网格信息  按照逐个网格的方式处理

                        int reanLineNumber = 0;//记录读取某一个网格的时候，从文件中读取的总行数，用以判断读取一个网格的数据是否结束

                        int readEndColNum = 0;//每个I（Row）占多行时，记录读取的局部行数，用以判断读取I（Row）是否结束

                        //下面使用 do   while  循环  读取数据，while中负责判断是否读到文件末尾或是否读完了一个网格的数据


                        string str=null ;
                        do
                        {
                            //循环读取一个网格的数据信息

                            #region

                             str = sr.ReadLine();

                            reanLineNumber = reanLineNumber + 1;


                            if (str == null)
                            {
                                _headCellCenter.Clear();

                                break;//当文件中间有空行不是连续的数据的时候  表示文件被破坏
                                //continue;
                            }
                            if (str.Trim() == "")
                            {
                                _headCellCenter.Clear();

                                break;//当文件中间有空行不是连续的数据的时候  表示文件被破坏
                                //continue;
                            }
                            if (lineNum <= 1)//网格每个I（Row）在文件中占1行
                            {
                                #region

                                for (int index = 0; index < _j; index++)
                                {
                                    //遍历读取完整数据 

                                    string colStr = str.Substring(index * mLen, mLen);

                                    double rowColData = Convert.ToDouble(colStr);

                                    //Grid3d.Datas[row, index, layer] = rowColData;

                                    gridValue[row, index, layer] = rowColData;

                                }
                                if (row + 1 >= _i)//判断是否读完了一层
                                {
                                    row = 0;
                                    layer = layer + 1;//改变层的标记
                                }
                                else
                                {
                                    row = row + 1;//记录正在读取网格的哪一个Row
                                }

                                #endregion

                            }
                            else
                            {
                                readEndColNum = readEndColNum + 1;//个数
                                if (readEndColNum > lineNum)//I（Row）对应的数据读完，进入下一个Row
                                {
                                    row = row + 1;
                                    col = 0;
                                    readEndColNum = 1;
                                }
                                if (row + 1 > _i)//判断是否读完了一层
                                {
                                    row = 0;
                                    col = 0;
                                    layer = layer + 1;//改变层的标记
                                }
                                //else
                                //{
                                //    row = row + 1;//记录正在读取网格的哪一个Row
                                //    col = 0;
                                //}


                                if (readEndColNum == lineNum)
                                {
                                    for (int index = 0; index < _j - (lineNum - 1) * maxLength; index++)
                                    {
                                        //遍历读取完整数据 

                                        string colStr = str.Substring(index * mLen, mLen);

                                        double rowColData = Convert.ToDouble(colStr);

                                        //Grid3d.Datas[row, col, layer] = rowColData;

                                        gridValue[row, col, layer] = rowColData;

                                        col = col + 1;

                                    }

                                }
                                else
                                {
                                    for (int index = 0; index < maxLength; index++)
                                    {
                                        //遍历读取完整数据 

                                        string colStr = str.Substring(index * mLen, mLen);

                                        double rowColData = Convert.ToDouble(colStr);

                                        //Grid3d.Datas[row, col, layer] = rowColData;

                                        gridValue[row, col, layer] = rowColData;

                                        col = col + 1;
                                    }

                                }

                                #region


                                #endregion

                            }

                            #endregion
                        }
                        while (sr.EndOfStream != true && reanLineNumber < gridLineNumber);


                        #endregion 从文件读取网格信息 结束

                        if (str == null)
                        {
                            break;
                        }
                        else if (str.Trim() == "")
                        {
                            break;
                        }
                        else
                        {

                     
                           

                            CellCenterDataSet3d headGridCellCenter = new CellCenterDataSet3d(gridValue, this.iBoundValue);
                            headGridCellCenter.Nrows = _i;
                            headGridCellCenter.Ncols = _j;
                            headGridCellCenter.Nlayers = _k;

                            headGridCellCenter.Label = stressIndex .ToString ()+"_"+timeIndex .ToString ();



                            //_heads.Add(Grid3d);

                            _headCellCenter.Add(headGridCellCenter);
                        }
                    

                    }//  for (int gnum = 0; gnum < gridNumber; gnum++)//总共多少个网格的数据  结束



                    sr.Close();

                }
                catch (Exception)
                {
                    System.Windows.Forms.MessageBox.Show("读取结果文件 IHEDUN.dat 出错了！");

                    //_heads.Clear();

                    _headCellCenter.Clear();

                    sr.Close();

                    //return _headCellCenter;
                }


                #endregion


            }


            for (int n = 0; n < _headCellCenter.Count; n++)
            {
                DataSet data = _headCellCenter[n];
                _headDataSet.Add(data);
            }



            return _headDataSet;


            //throw new NotImplementedException();



        }



        #endregion




    }
}
